


static map skillsConf = ({});


///*实际伤害 = [(攻击方.str + 攻击方.combatExp / 100) * (1 + 攻击方.int / 100)] - (防御方.con / 2)
//
//若 攻击方.dex / 防御方.dex > 随机数(0, 1)，则攻击方躲避防御方反击
//若 防御方.dex / 攻击方.dex > 随机数(0, 1)，则防御方躲避攻击，实际伤害 = 0*/

static number fight(object me, object victim){

    map kEntire = me.entityData();
    map vEntire = victim.entityData();
    //伤害
    number kdmg = ( kEntire["str"] + kEntire["combatExp"] / 100 ) * (1 + kEntire["int"] / 100) ;
//    println(me.query("name")+" 开始伤害是"+kdmg);

    number vDef =  vEntire["con"] / 2;
    kdmg = kdmg - vDef;

    if (randomRange(0,5) < vEntire["dex"] / kEntire["dex"]){
        println("没打中");
    }else{
        vEntire["qi"] -= kdmg;
    }


    println(fmt("%s 气是 %s",victim.query("name"),vEntire["qi"]));

    if( vEntire["qi"] < 1  ){
        string msg = fmt("%s 口吐鲜血，一口气上不来死了。",victim.query("name"));
        tellObject(me,msg);
        println(msg);

        me.removeKiller(victim);
        victim.die();
//
        me.set("pot",me.query("pot")+20);
        tellObject(me,fmt("战斗胜利 修为 + %s",20));
        return 1;
    }

    println(fmt("%s(%s) -> %s(%s)",me.query("name"),kEntire["qi"],victim.query("name"),vEntire["qi"]));


}


//获取物理站位的名称
static string posDesc(number posId){
    string desc;
    if( posId==1 ){
        desc="左(后上)";
    }else if(posId==2){
        desc="左(后中)";
    }else if(posId==3){
        desc="左(后下)";
    }else if(posId==4){
        desc="左(前上)";
     }else if(posId==5){
         desc="左(前中)";
     }else if(posId==6){
         desc="左(前下)";
     }else if(posId==7){
          desc="右(前上)";
      }else if(posId==8){
          desc="右(前中)";
      }else if(posId==9){
          desc="右(前下)";
       }else if(posId==10){
           desc="右(后上)";
       }else if(posId==11){
           desc="右(后中)";
       }else if(posId==12){
           desc="右(后下)";
       }else{
            desc="位置数据错误!";
       }
       return desc;
}

static number getPosOf(number vPosId,map target){
    foreach(e in target){
        println(e);
    }
}
//计算伤害
static number calcDamage(map killer,map buf,number baseDamage,map scoreContext){

 if(  buf["resultType"] > 1){//调整比例
    if( buf["refChangeType"]==1 && buf["refTarget"]==1){//增加模式
        baseDamage += baseDamage * buf["refChangeVal"];
    }
  }

  number rankDmg = baseDamage * (killer["rank"] * 0.015);
  number oldDmg = baseDamage;
  baseDamage +=rankDmg;

  scoreContext["combatDebugMsg"]+=fmt(" -> 阶位提升的伤害 %s -> %s | ↑ %s\n",oldDmg, baseDamage,rankDmg);


  if(  sizeof(killer["effs"]) > 0 ){
    foreach( e in killer["effs"]){
        if( e["type"] == "减伤" && e["duration"] > 0){
//            println(fmt("减伤 %s",baseDamage * e["refChangeVal"]));
            baseDamage-= baseDamage * e["refChangeVal"];
        }
    }
  }


  return baseDamage;
}

static number rdKill(map killer,map kSkillData,map kBuf, map victim,map scoreContext,string* combatMessage){


    //伤害
    number kdmg = ( killer["str"] + killer["combatExp"] / 100 ) * (1 + killer["int"] / 100) ;


    number vDef =  victim["con"] / 2;
    kdmg = kdmg - vDef;
    number rand = randomRange(0,5);
    number dexRate = victim["dex"] / killer["dex"];


    var attackSk = killer["skills"]["attack"];

    if( !this::skillsConf ){
        println("skillConf没有数据啊!");
        return 1;
    }
    map skillData = kSkillData;


    map buf = kBuf;//skillData["bufs"][random(sizeof(skillData["bufs"]))];
    map carryEffect = ({});
    //恢复类效果的值
    number recoverVal;

    object kOb = killer["teamLeader"];
    object vOb = victim["teamLeader"];
    string skName = skillData["name"];
    string skBufName = buf["name"];
    string kPosDesc = this::posDesc(killer["pPos"]);
    string vPosDesc = this::posDesc(victim["pPos"]);
    string* kmsg;
//    string batMsg1 = fmt("%s(%s)<%s> 使出 %s(%s) 攻击 %s(%s)<%s> ",killer["name"],killer["qi"],kPosDesc,  skillData["name"],buf["name"],victim["name"],victim["qi"],vPosDesc);

    //[回合N] 大当家(气血:200/200 | 能量:50/50)<左(前下)> 释放技能「十八摸·抓手」(消耗能量20)

    string kStr =  fmt("[回合%s] %s(气:%s/%s | 能:%s/%s)<%s>",scoreContext["rounCount"],killer["name"],killer["qi"],killer["maxQi"],killer["neili"],killer["maxNeili"],kPosDesc);
    string vStr = fmt(" -> 目标: %s(气:%s/%s | 能:%s/%s)<%s>\n",victim["name"],victim["qi"],victim["maxQi"],victim["neili"],victim["maxNeili"],vPosDesc);
    string btMsg="";

    string kTitle = fmt("%s(气 %s/%s 能 %s/%s)<%s>",killer["name"],killer["qi"],killer["maxQi"],killer["neili"],killer["maxNeili"],kPosDesc);
    string vTitle = fmt("%s(气 %s/%s 能 %s/%s)<%s>",victim["name"],victim["qi"],victim["maxQi"],victim["neili"],victim["maxNeili"],vPosDesc);
    string actType;
    string skillMsg;
    string batMsg;
    string effMsg="";



    number hitTrue = 0;
    //能量够用 默认够用
    number canNeili = 1;
    //执行前的能量
    number befNeili = killer["neili"];

    //技能需要消耗的能量比率
     number costNeili = 0;

    skillMsg = fmt("使出 %s(%s) 耗能 %s",skName,skBufName,buf["costNeili"] > 0 ? "是":"否");

    scoreContext["combatDebugMsg"]+= kStr+fmt("%s 使出 %s(%s) 耗能 %s\n",killer["name"],skName,skBufName,buf["costNeili"] > 0? "是":"否");
    scoreContext["combatDebugMsg"]+=vStr;

    if( buf["costNeili"] > 0 ){
        costNeili = killer["maxNeili"] * buf["costNeili"];
    }

    if( buf["type"]=="物理攻击" ){//物理攻击也可能需要消耗能量

        if(costNeili > 0 && killer["neili"] - costNeili < 1){
            canNeili = 0;
        }

        kdmg = calcDamage(killer,buf,kdmg,scoreContext);
        actType = "攻击";
        if (rand < dexRate || !canNeili){
            batMsg = fmt("但没打中%s",victim["name"]);
            scoreContext["combatDebugMsg"]+=fmt(" -> 结果:未命中 原因 %s < %s || %s\n",rand,dexRate,canNeili<=0?"能量不足":"能量充足");
        }else{

             hitTrue = 1;

             scoreContext["combatDebugMsg"]+=fmt(" -> 结果:命中 造成 %s 点伤害,目标气血剩余 %s - %s =",kdmg,victim["qi"],kdmg);

             victim["qi"] -= kdmg;

             scoreContext["combatDebugMsg"]+=fmt(" %s\n",victim["qi"]);

             if( costNeili > 0 ){
               killer["neili"] -= costNeili;
             }


            //会不会给对方贴上buf?
            if( has( buf,"afterEffect") && has(buf["afterEffect"],"effs") && sizeof(buf["afterEffect"]["effs"]) > 0 ){
                foreach( e in buf["afterEffect"]["effs"] ){
                    if( !canSetBuf(victim,e) ) continue;

                    e["duration"] = e["cycle"];
                    effMsg+=fmt(" %s 持续%s回合、", e["name"], e["cycle"]);

                    if( !victim["effs"] ){
                        victim["effs"] = ([]);
                        victim["effs"]+=e;
                    }else{
                         victim["effs"]+=e;
                    }
                }
            }
            batMsg = fmt("造成 %s 点伤害。",kdmg);
            if( effMsg ){
                scoreContext["combatDebugMsg"]+=fmt(" -> 附加效果:%s\n",effMsg);
                batMsg+= "还附加了Buf "+effMsg;
            }
        }
    }
    else if( buf["type"] == "治疗"){

//        var aef = buf["afterEffect"]["bufs"][0];
        carryEffect["triggerOdds"]      = buf["triggerOdds"];
        carryEffect["refChangeVal"]     = buf["refChangeVal"];
        carryEffect["resultType"]       = buf["resultType"];
        carryEffect["refTarget"]        = buf["refTarget"];
        carryEffect["refChangeType"]    = buf["refChangeType"];
        carryEffect["costNeili"]        = buf["costNeili"];

        if( buf["resultType"] > 1 && buf["refChangeType"]==1 ){//增加模式
            if(  buf["refTarget"]==4  ){//参考
                recoverVal = victim["maxQi"] * buf["refChangeVal"];
            }
        }

        actType = "治疗";

        if(  killer["neili"] - costNeili > 0 ){
            killer["neili"] -= costNeili;
            victim["qi"]+=recoverVal;

            scoreContext["combatDebugMsg"]+=fmt(" -> 结果:命中 恢复 %s 点气,目标气剩余 %s\n",recoverVal,victim["qi"]);

            batMsg = fmt("%s 恢复了 %s 点气血",victim["name"],recoverVal);
        }else{
            scoreContext["combatDebugMsg"]+=fmt(" -> 结果:未命中 原因 (能量)%s - (耗能)%s = (剩余)%s\n",killer["neili"],costNeili,killer["neili"]-costNeili);
            batMsg = "结果能量不足！";
        }

        //预防超量恢复
        if( victim["qi"] > victim["maxQi"] ){
            victim["qi"] = victim["maxQi"];
        }

    }else{

    }


    scoreContext["combatDebugMsg"]+=fmt(" -> 执行者状态 : 能量 %s - %s = %s\n",befNeili, costNeili  ,killer["neili"]);

    println(scoreContext["combatDebugMsg"]);

    batMsg = fmt( "%s %s %s %s %s", kTitle, skillMsg, actType,vTitle,batMsg );



    combatMessage+=batMsg;

   if( victim["qi"] < 1  ){
        combatMessage+=fmt("%s(%s) 口吐鲜血，一口气上不来死了。",victim["name"],victim["qi"]);
//             if( kOb.query("isUser")  ){
//                   kOb.add("combat/reward/pot",20);
//                   combatMessage+=fmt("%s(%s) 口吐鲜血，一口气上不来死了。",victim["name"],victim["qi"]);
//             }
       return 1;
   }




//    println(fmt("%s(%s) -> %s(%s)",killer["name"],killer["qi"],victim["name"],victim["qi"]));



}

//是否能给目标设置Buf
static number canSetBuf(map victim,map buf){

    if( victim["effs"] && sizeof( victim["effs"] ) > 0 ){
        foreach(e in victim["effs"]){
            if( buf["type"]==e["type"] ) return 0;
        }
    }
    return 1;
}

static map* crRound(object k, object v){

    //回合唯一ID

    k.set("combatMessage",([]));
    v.set("combatMessage",([]));

    k.set("rGame/skills/attack","100001");
    k.set("rGame/skills/defense","100002");

     v.set("rGame/skills/attack","100003");
     v.set("rGame/skills/defense","100004");
     map sk1 = ({
        "rGame":({
            "skills":({
                "attack":"100003"
            })
        })

     });

          map sk2 = ({
             "rGame":({
                 "skills":({
                     "attack":"100002"
                 })
             })

          });

//     println("技能显示");
//     println(sk1["rGame"]["skills"]);




    map* que = ([
        ({
             "teamId":k.id(),
             "teamLeader":k,
             "name":k.query("name"),
             "qi":k.query("qi"),
             "maxQi":k.query("maxQi"),
             "neili":k.query("neili"),
             "maxNeili":k.query("maxNeili"),
             "str":k.query("str"),
             "int":k.query("int"),
             "dex":k.query("dex"),
             "rank":1,
             "combatExp":k.query("combatExp"),
             "skills":k.query("rGame/skills"),
             "con":k.query("con"),
             //虚拟站位 玩家vs玩家时  玩家始终在右边 6格
             "vPos":1,
             //物理站位
             "pPos":6

        }),
         ({
                     "teamId":k.id(),
                      "teamLeader":k,
                     "name":"老色鬼",
                     "qi":100,
                     "maxQi":100,
                      "neili":100,
                      "maxNeili":100,
                      "str":15,
                      "int":15,
                      "dex":15,
                      "rank":1,
                      "combatExp":0,
                       "skills":sk1["rGame"]["skills"],
                      "con":15,
                       "vPos":4,
                       //物理站位
                       "pPos":5

          }),
         ({
             "teamId":v.id(),
              "teamLeader":v,
             "name":v.query("name"),
             "qi":v.query("qi"),
             "maxQi":v.query("maxQi"),
              "neili":v.query("neili"),
              "maxNeili":v.query("maxNeili"),
              "str":v.query("str"),
              "int":v.query("int"),
              "dex":v.query("dex"),
              "rank":9,
              "combatExp":v.query("combatExp"),
               "skills":v.query("rGame/skills"),
              "con":v.query("con"),
               "vPos":1,
               //物理站位
               "pPos":7
        }),

         ({
                     "teamId":v.id(),
                      "teamLeader":v,
                     "name":"赵灵儿",
                     "qi":100,
                     "maxQi":100,
                      "neili":100,
                      "maxNeili":100,
                      "str":15,
                      "int":15,
                      "dex":15,
                      "rank":2,
                      "combatExp":0,
                       "skills":sk2["rGame"]["skills"],
                      "con":15,
                       "vPos":5,
                       //物理站位
                       "pPos":11
                })

    ]);

    return que;


}

//prev 上一回合数据
static map* nextRound(map *prev){
    //回合唯一ID
    map* nQue = ([]);
    foreach(k in prev){
          k["haveBeenAttack"]=0;
         if( k["qi"] > 0){
           nQue+=k;
         }
    }
    return nQue;
}

//获取对手阵营数据
static map* getEnemyLists(map killer,map* que){
    map* enemys  = ([]);
    foreach(e in que){
        if( e["teamId"]!=killer["teamId"] && e["qi"] > 0 ){
            enemys+=e;
        }
    }
    return enemys;
}
//获取我方成员数据
static map* getAllieLists(map killer,map* que){
    map* enemys  = ([]);
    foreach(e in que){
        if( e["teamId"]==killer["teamId"] && e["qi"] > 0 ){
            enemys+=e;
        }
    }
    return enemys;
}



//我方或者地方的前排
static map* getFront(map* enemys){
    map* enemyLists = ([]);
    foreach( e in enemys ){
        if( e["vPos"] > 0  && e["vPos"] < 4  ){
            enemyLists+=e;
        }
    }
    return enemyLists;
}

//我方或者地方的后排
static map* getBack(map* enemys){
    map* enemyLists = ([]);
    foreach( e in enemys ){
        if( e["vPos"] > 3  && e["vPos"] < 7  ){
            enemyLists+=e;
        }
    }
    return enemyLists;
}


static map getSkiData(map killer){
 //提取出技能
     var attackSk = killer["skills"]["attack"];
    if( !this::skillsConf ){
        println("skillConf没有数据啊!");
        return 1;
    }
    map skillData = this::skillsConf[attackSk];
    if( !skillData ){
        println(attackSk+" 没有找到技能文件");
    }
    return skillData;
}


//从对手集合中随机获取一个对手
static number getEnemyOfRandom(map* enemyQue){
    map enemy = enemyQue[ random(sizeof(enemyQue)-1)  ];
    return enemy;
}

static number selectEnemy(map killer,map* que,number currRound,string* combatMessage){

    map sk = getSkiData(killer);

    map buf = sk["bufs"][random(sizeof(sk["bufs"]))];
    var enemyLists = ([]);
     //1我方前排 2我方后排 3我方所有 4我自己（使用技能的人） 5敌方前排 6敌方后排 7敌方所有 8上一次攻击 9相同占位
    var emys ;

//    if( sizeof(emys) < 1 ) return 3;
    if( buf["findDomain"] == 5 ){//技能要求选择敌方前排
        emys = getEnemyLists(killer,que);
        enemyLists = getFront( emys );
    }else if(buf["findDomain"] == 1){//我方前排
        emys = getAllieLists(killer,que);
        enemyLists = getFront( emys );
    }else{
        emys = getEnemyLists(killer,que);
    }

    //    //对面都没人了...
    if( sizeof(emys) < 1 ) return 3;

    if( !enemyLists || sizeof(enemyLists) < 1 ) enemyLists+= emys[random(sizeof(emys)-1)];


    foreach(kv in enemyLists){
        this::rdKill(killer,sk,buf,kv,currRound,combatMessage);
        return 1;
    }
}



static number getReming(string id,map* que){
    number n=0;
    foreach( k in que ){
        if( k["teamId"]==id ) n++;
    }
    return n;
}


//每个回合 执行buf
static number evalBufs(map k){
    number n = sizeof(k["effs"]);
    string msg="";
    if( n > 0 ){

        number addn=0,tmpN=0;
        number effMsg="";
        foreach( e in k["effs"] ){

            if( e["type"]=="吸血" ){
                addn = k["qi"] * e["refChangeVal"];
                tmpN = k["qi"];
                k["qi"]-=addn;
                effMsg+=fmt("%s 目标状态 气 %s - %s = %s\n",e["type"], tmpN,addn,k["qi"] );
            }

            e["duration"]--;
            msg+=fmt("%s 持续回合剩余%s",e["name"],e["duration"]);
        }

        //过滤掉不需要的
        k["effs"] = filterArray( k["effs"],(e)->{
            return e["duration"] > 0 ;
        });
      msg=fmt("[出手前特效处理] %s %s 剩余特效数量 %s\n",k["name"],msg,sizeof(k["effs"]));
      msg+=effMsg;
      println(msg);


    }

    return 1;

}

//能量恢复
static number recoverNeli(map k){
         number recoverVal,curNeili;
        if( k["qi"] < 1 ) return 1;
        curNeili = k["neili"];
        if(  k["neili"] < k["maxNeili"] ){
             recoverVal = k["maxNeili"] * 0.02;
             k["neili"]+=recoverVal;
        }

        if( k["neili"] > k["maxNeili"] ){
            k["neili"] = k["maxNeili"];
        }
        string s = fmt("[出手后能量恢复] %s %s + %s = %s",k["name"],curNeili,recoverVal,k["neili"]);
        println(s);

}

static number roundFight(object me, object victim){

    map kEntire = me.entityData();
    map vEntire = victim.entityData();

    //构建回合制调度器 交替回合制 所有人出手完成 算一回合

    //获取第n回合 战斗序列
    map* que =  this::crRound(me,victim);

    //如果是PVP 则是两个玩家
    object player = findPlayerObj(que);

    //提取队列分组ID
    string a1Id = me.id();
    string a2Id = victim.id();

    string* combatMessage = ([]);
    //战斗场景的上下文信息
    map scoreContext = ({});

    scoreContext["rounCount"] = 1;
    scoreContext["combatDebugMsg"] = "";

    for(  ;; ){
        foreach(k in que){
            if( k["qi"] < 1 ) continue;
             //是否有buf
            evalBufs(k);
            selectEnemy(k,que,scoreContext,combatMessage);
            //恢复能量
            recoverNeli(k);
        }


        scoreContext["rounCount"]++;
        que = nextRound( que );
        if( getReming(a1Id,que) < 1 || getReming(a2Id,que) < 1  ) break;

    }

    println(combatMessage);
    //把战斗记录挂载玩家身上
    player.set("combatMessage",combatMessage);
    println( fmt("%s 回合后 剩下的队伍%s",scoreContext["rounCount"],toJsonStr(que)) );

}


static object findPlayerObj(map* que){
    foreach( e in que ){
        if( e["teamLeader"].query("isUser") ){
            return e["teamLeader"];
        }
    }
    return 0;
}



static number testCron(string param){
    println("被计划调用咯"+param);
}